#include <iostream>
#include <string>
#include "SignalSlot.h"


class String
{
public:
    String(const char* str)
    {
        printf("String ctor this %p\n", this);
    }

    String(const String& rhs)
    {
        printf("String copy ctor this %p, rhs %p\n", this, &rhs);
    }

    String(String&& rhs)
    {
        printf("String move ctor this %p, rhs %p\n", this, &rhs);
    }
};

class Foo : noncopyable
{
public:
    void zero();
    void zeroc() const;
    void one(int);
    void oner(int&);
    void onec(int) const;
    void oneString(const String& str);
    // void oneStringRR(String&& str);
    static void szero();
    static void sone(int);
    static void soneString(const String& str);
};

void Foo::zero()
{
    printf("Foo::zero()\n");
}

void Foo::zeroc() const
{
    printf("Foo::zeroc()\n");
    std::cout << " completed by thread " << std::this_thread::get_id() << std::endl;
}

void Foo::szero()
{
    printf("Foo::szero()\n");
}

void Foo::one(int x)
{
    printf("Foo::one() x=%d\n", x);
}

void Foo::onec(int x) const
{
    printf("Foo::onec() x=%d\n", x);
}

void Foo::sone(int x)
{
    printf("Foo::sone() x=%d\n", x);
}

void Foo::oneString(const String& str)
{
    printf("Foo::oneString\n");
}

void Foo::soneString(const String& str)
{
    printf("Foo::soneString\n");
}

int main() {
    muduo::Signal<void()> signal;

    printf("==== testSignalSlotZero ====\n");
    signal.call();

    muduo::Slot s1 = signal.connect(&Foo::szero);

    printf("========1\n");
    signal.call();

    Foo f;
    muduo::Slot s2 = signal.connect(std::bind(&Foo::zero, &f));

    printf("========2\n");
    signal.call();

    muduo::Slot s3 = signal.connect(std::bind(&Foo::one, &f, 42));

    printf("========3\n");
    signal.call();

    const Foo cf;
    muduo::Slot s4 = signal.connect(std::bind(&Foo::zeroc, &cf));

    printf("========4\n");
    signal.call();

    muduo::Slot s5 = signal.connect(std::bind(&Foo::onec, &cf, 128));

    printf("========5\n");
    signal.call();

    {
        muduo::Slot s6 = signal.connect(std::bind(&Foo::onec, &cf, 59));
        signal.disconnect(s6);
        printf("s6 will destruct aftersoon\n");
    }
    printf("s6 is destructed\n");

    signal.disconnect(s5); //128 will disconnect  s5会等到离开作用域之后被析构

    s1 = muduo::Slot();  //s1 will disconnect，该方法会使signal中的相应的slot对象被释放，之后会清理槽函数列表容器中的weak_ptr
    printf("========6\n");
    signal.call();


    s4 = s3 = s2 = muduo::Slot();
    printf("========7\n");
    signal.call();
    printf("========8\n");

    /*
     * connect(Callback&& func, const std::shared_ptr<void>& tie)的使用，当tie被销毁后，相应的slot不会执行
     * std::bind 绑定std::shared_ptr的对象会增加其引用计数
     *
     */

    std::shared_ptr<Foo> pF = std::make_shared<Foo>();
    auto qw = std::bind(&Foo::one, pF, 1314);

    printf("pF count %ld\n", pF.use_count());
    muduo::Slot s6 = signal.connect(std::bind(&Foo::one, pF, 1314), pF);
    muduo::Slot s7 = signal.connect(&Foo::szero, pF);
    muduo::Slot s8 = signal.connect(std::bind(&Foo::zeroc, &cf), true);

    //const std::shared_ptr<Foo> pFtmp = pF;

    printf("pF count %ld\n", pF.use_count());

    pF.reset();
    pF = nullptr;

    printf("pF count %ld\n", pF.use_count());

    signal.call();
    printf("========9\n");

    printf("========10\n");
    std::cout << " main thread is " << std::this_thread::get_id() << std::endl;

    muduo::CallExtension(Sig::readFile);
    muduo::CallExtension(Sig::recvFile);


    return 0;
}
